﻿using System;
using System.Data;
using System.Data.Common;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using SuvirinimaiApp.Properties;

namespace SuvirinimaiApp
{
    public enum ColumnType { intg, date, text, booln };
    internal struct rikiavimas
    {
        internal string columnName;
        internal bool ascending;

        internal rikiavimas(string coln, bool scend)
        {
            columnName = coln;
            ascending = scend;
        }
    }
    public partial class fAktai : Form
    {
        private BindingSource bindingSource;
        private DbDataAdapter dAdapter;
        private DbConnection conn;
        private DataTable dTable;
        private DataView dView;
        private string visiAktaiSql;
        private string savedFilter = string.Empty;
        private string savedOrder = string.Empty;
        protected bool hasChanges;
        List<string> filterElements = new List<string>();
        ArrayList rikiavimai = new ArrayList();
        string cc = " AND "; // current connector

        public fAktai()
        {
            InitializeComponent();
            dAdapter = Program.dpf.CreateDataAdapter();
            conn = Program.dpf.CreateConnection();
            conn.ConnectionString = Program.connectionString;
            dAdapter.SelectCommand = Program.dpf.CreateCommand();
            dAdapter.SelectCommand.Connection = conn;
            dTable = new DataTable();
            bindingSource = new BindingSource();
            buildUpdateCommand();
        }

        private void fVisiSuvirinimai_Load(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder("SELECT ");
            sb.Append("Aktai.id, Aktai.aktas_Nr, Aktai.aktas_data, Aktai.aktas_arUzbaigtas, Aktai.aktas_trukumai, Aktai.aktas_arAtitinkaData, Aktai.aktas_arAtitinkaVieta, ");
            sb.Append("Padaliniai.pavadinimas, Aktai.aktas_padalinysId, ");
            sb.Append("Aktai.k11, Aktai.k12, Aktai.k21, Aktai.k22, Aktai.k23, Aktai.k24, Aktai.k31, Aktai.k32, Aktai.k41, Aktai.k42, Aktai.k51, ");
            sb.Append("Operatoriai.vardas, ");
            sb.Append("Aktai.tikrin_arDefektas, Aktai.tikrin_rezultatas, Aktai.tikrin_operatoriusId ");
            sb.Append("FROM ");
            sb.Append("(Aktai LEFT JOIN Padaliniai ON Aktai.aktas_padalinysId=Padaliniai.id) ");
            sb.Append("LEFT JOIN Operatoriai ON Aktai.tikrin_operatoriusId=Operatoriai.id ");
            sb.Append("ORDER BY Aktai.id DESC;");
            visiAktaiSql = sb.ToString();
            dAdapter.SelectCommand.CommandText = visiAktaiSql;
            doColumns();
            query();
        }

        private void query()
        {
            try
            { savedFilter = dView.RowFilter; }
            catch
            { savedFilter = string.Empty; }

            try
            { savedOrder = dView.Sort; }
            catch
            { savedOrder = "id DESC"; }

            dTable.Clear();            
            dAdapter.Fill(dTable);
            dView = new DataView(dTable, savedFilter, savedOrder, DataViewRowState.CurrentRows);
            bindingSource.DataSource = dView;
            dgvAktai.DataSource = bindingSource;

            hasChanges = false;
            tsbSave.Enabled = false;
            updateStatusBar();

        }

        private void doColumns()
        {
            dgvAktai.AutoGenerateColumns = false;
            foreach (DataGridViewColumn column in dgvAktai.Columns)
            {
                column.DataPropertyName = column.Name;
            }

            //dgvAktai.AutoResizeColumns();
            dgvAktai.Columns["aktas_trukumai"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        }

        private void doFilter()
        {
            if (filterElements.Count > Settings.Default.MaxFilterParts)
            {
                Msg.ExclamationMsg(string.Format(Messages.Per_ilgas_filtras, Settings.Default.MaxFilterParts));
                while (filterElements.Count > Settings.Default.MaxFilterParts)
                    filterElements.RemoveAt(filterElements.Count - 1);
            }
            dView.RowFilter = String.Join(cc, filterElements);
            updateStatusBar();
        }

        private void updateStatusBar()
        {
            lblStatusFilter.Text = "Filtras: " + dView.RowFilter + "  Rikiavimas: " + dView.Sort;
            lblStatus.Text = "Įrašų: " + dView.Count.ToString();
        }
        
        private string makeFilterByCell(DataGridViewCell cl)
        {
            string columnName = dgvAktai.Columns[cl.ColumnIndex].Name;
            switch (columnName)
            {
                case "aktas_Nr":
                    return makeFilterString(columnName, cl.Value, ColumnType.text);
                case "aktas_data":
                    return makeFilterString(columnName, cl.Value, ColumnType.date);
                case "pavadinimas":
                    return makeFilterString("aktas_padalinysId", dgvAktai.Rows[cl.RowIndex].Cells["aktas_padalinysId"].Value, ColumnType.intg);
                case "k11":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k12":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k21":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k22":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k23":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k24":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k31":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k32":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k41":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k42":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "k51":
                    return makeFilterString(columnName, cl.Value, ColumnType.intg);
                case "vardas":
                    return makeFilterString("tikrin_operatoriusId", dgvAktai.Rows[cl.RowIndex].Cells["tikrin_operatoriusId"].Value, ColumnType.intg);
                case "tikrin_arDefektas":
                    return makeFilterString(columnName, cl.Value, ColumnType.booln);
                case "tikrin_rezultatas":
                    return makeFilterString(columnName, cl.Value, ColumnType.text);
                case "aktas_arUzbaigtas":
                    return makeFilterString(columnName, cl.Value, ColumnType.booln);
                case "aktas_arAtitinkaData":
                    return makeFilterString(columnName, cl.Value, ColumnType.booln);
                case "aktas_arAtitinkaVieta":
                    return makeFilterString(columnName, cl.Value, ColumnType.booln);
                case "aktas_trukumai":
                    return makeFilterString(columnName, cl.Value, ColumnType.text);
                default:
                    return string.Empty;
            }
        }

        private string makeFilterString(string parameterName, object cellValue, ColumnType type)
        {
            if (cellValue == null) // || string.IsNullOrEmpty(cellValue.ToString())
                return string.Format("{0} IS NULL", parameterName);

            switch (type)
            {
                case ColumnType.intg:
                    return string.Format("{0}={1}", parameterName, cellValue.ToString());

                case ColumnType.date:
                    return string.Format("{0}={1}", parameterName, DbHelper.formatDateValue(cellValue));

                case ColumnType.text:
                    return string.Format("{0}={1}", parameterName, string.Format("'{0}'", sanit(cellValue)));

                case ColumnType.booln:
                    return string.Format("{0}={1}", parameterName, cellValue.ToString());

                default:
                    return string.Empty;
            }
        }
        
        private void unfilter()
        {
            // numeta filtrą ir rūšiavimą
            dView.RowFilter = string.Empty;
            filterElements.Clear();
            updateStatusBar();
        }

        private string sanit(object controlValue)
        {
            // išvalo stringus nuo sql neleistinų simbolių - ' ir "
            // (nors gal būtų galima escapinti?)
            string strToSanitize = string.Empty;
            try
            {
                strToSanitize = controlValue.ToString();
            }
            catch
            {
                return string.Empty;
            }

            Regex forb = new Regex("['\"]*");
            return forb.Replace(strToSanitize, string.Empty).Trim();
        }

        private void tsmiFileClose_Click(object sender, EventArgs e)
        {
            if (hasChanges)
            {
                DialogResult result = Msg.YesNoCancelQuestionMsg(Messages.Yra_pakeitimu_Ar_issaugoti);

                if (result == DialogResult.No)  // pakeitimų yra, bet neišsaugoti
                {
                    Close();
                }
                else if (result == DialogResult.Cancel) // pakeitimų yra, bet nutraukti veiksmą
                {
                    return;
                }
                else   // pakeitimų yra ir išsaugoti
                {
                    endEditAndSave();
                    Close();
                }
            }
            else // pakeitimų nėra - išeiti ir viskas
            {
                Close();
            }
        }

        private void tsmiPadaliniai_Click(object sender, EventArgs e)
        {
            using (TvarkytiPadaliniai frmPadaliniai = new TvarkytiPadaliniai())
            {
                frmPadaliniai.ShowDialog();
            }
        }

        private void tsmiOperatoriai_Click(object sender, EventArgs e)
        {
            using (TvarkytiOperatoriai frmOperatoriai = new TvarkytiOperatoriai())
            {
                frmOperatoriai.ShowDialog();
            }
        }

        private void tsmiDefektoskopai_Click(object sender, EventArgs e)
        {
            using (TvarkytiDefektoskopai frmDefektoskopai = new TvarkytiDefektoskopai())
            {
                frmDefektoskopai.ShowDialog();
            }
        }

        private void tsmiBegiuTipai_Click(object sender, EventArgs e)
        {
            using (TvarkytiBegiuTipai frmBegiuTipai = new TvarkytiBegiuTipai())
            {
                frmBegiuTipai.ShowDialog();
            }
        }

        private void tsmiMisiniai_Click(object sender, EventArgs e)
        {
            using (TvarkytiMisiniai frmMisiniai = new TvarkytiMisiniai())
            {
                frmMisiniai.ShowDialog();
            }
        }

        private void tsmiSuvirintojai_Click(object sender, EventArgs e)
        {
            using (TvarkytiSuvirintojai frmSuvirintojai = new TvarkytiSuvirintojai())
            {
                frmSuvirintojai.ShowDialog();
            }
        }

        private void tsmiDarbuVadovai_Click(object sender, EventArgs e)
        {
            using (TvarkytiVadovai frmDVadovai = new TvarkytiVadovai())
            {
                frmDVadovai.ShowDialog();
            }
        }

        private void endEditAndSave()
        {
            //MessageBox.Show("Įrašomi atlikti pakeitimai...");
            dgvAktai.EndEdit(DataGridViewDataErrorContexts.Commit);
            bindingSource.EndEdit();
            dAdapter.Update(dTable);

            hasChanges = false;
            tsbSave.Enabled = false;
        }

        private void dgvAktai_SelectionChanged(object sender, EventArgs e)
        {
            if (dgvAktai.CurrentRow != null && dgvAktai.Rows[dgvAktai.CurrentRow.Index].Selected == true)
            {
                tsbDeleteRecord.Enabled = true;
            }
            else
            {
                tsbDeleteRecord.Enabled = false;
            }
        }

        private void buildUpdateCommand()
        {
            StringBuilder updSql = new StringBuilder("UPDATE Aktai SET ");
            updSql.Append("aktas_Nr=@aktasNr, ");
            updSql.Append("tikrin_arDefektas=@arDefektas, ");
            updSql.Append("tikrin_rezultatas=@defektoKodas, ");
            updSql.Append("aktas_arAtitinkaData=@arAtitinkaData, ");
            updSql.Append("aktas_arAtitinkaVieta=@arAtitinkaVieta, ");
            updSql.Append("aktas_trukumai=@aktoTrukumai, ");
            updSql.Append("aktas_arUzbaigtas=@aktasArUzbaigtas ");
            updSql.Append("WHERE id=@ID;");

            DbCommand updateCommand = Program.dpf.CreateCommand();
            updateCommand.CommandText = updSql.ToString();

            DbParameter param0 = Program.dpf.CreateParameter();
            param0.ParameterName = "@aktasNr";
            param0.SourceColumn = "aktas_Nr";
            param0.DbType = DbType.String;
            updateCommand.Parameters.Add(param0);

            DbParameter param1 = Program.dpf.CreateParameter();
            param1.ParameterName = "@arDefektas";
            param1.SourceColumn = "tikrin_arDefektas";
            param1.DbType = DbType.Boolean;
            updateCommand.Parameters.Add(param1);

            DbParameter param2 = Program.dpf.CreateParameter();
            param2.ParameterName = "@defektoKodas";
            param2.SourceColumn = "tikrin_rezultatas";
            param2.DbType = DbType.String;
            updateCommand.Parameters.Add(param2);

            DbParameter param3 = Program.dpf.CreateParameter();
            param3.ParameterName = "@arAtitinkaData";
            param3.SourceColumn = "aktas_arAtitinkaData";
            param3.DbType = DbType.Boolean;
            updateCommand.Parameters.Add(param3);
            
            DbParameter param4 = Program.dpf.CreateParameter();
            param4.ParameterName = "@arAtitinkaVieta";
            param4.SourceColumn = "aktas_arAtitinkaVieta";
            param4.DbType = DbType.Boolean;
            updateCommand.Parameters.Add(param4);

            DbParameter param5 = Program.dpf.CreateParameter();
            param5.ParameterName = "@aktoTrukumai";
            param5.SourceColumn = "aktas_trukumai";
            param5.DbType = DbType.String;
            updateCommand.Parameters.Add(param5);
            
            DbParameter param6 = Program.dpf.CreateParameter();
            param6.ParameterName = "@aktasArUzbaigtas";
            param6.SourceColumn = "aktas_arUzbaigtas";
            param6.DbType = DbType.Boolean;
            updateCommand.Parameters.Add(param6);

            DbParameter param7 = Program.dpf.CreateParameter();
            param7.ParameterName = "@ID";
            param7.SourceColumn = "id";
            param7.DbType = DbType.Int32;
            updateCommand.Parameters.Add(param7);

            dAdapter.UpdateCommand = updateCommand;
            dAdapter.UpdateCommand.Connection = conn;
        }

        private void dgvAktai_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            hasChanges = true;
            tsbSave.Enabled = true;
        }

        private void tsbNew_Click(object sender, EventArgs e)
        {
            using (fAktas fNaujasAktas = new fAktas())
            {
                fNaujasAktas.ShowDialog();
            }
            query();
        }

        private void tsbSimilar_Click(object sender, EventArgs e)
        {
            DataGridViewCell cl = dgvAktai.CurrentCell;

            // nefiltruoti, jeigu nieko nerodo
            if (cl.RowIndex < 0) return;

            long currentRecordId = Convert.ToInt64(dgvAktai.CurrentRow.Cells["id"].Value);

            using (fAktas fPanasusAktas = new fAktas(currentRecordId, true))
            {
                fPanasusAktas.ShowDialog();
            }
            query();
        }

        private void tsbEdit_Click(object sender, EventArgs e)
        {
            long currentRecordId = Convert.ToInt64(dgvAktai.CurrentRow.Cells["id"].Value);
            using (fAktas fTasAktas = new fAktas(currentRecordId, false))
            {
                fTasAktas.ShowDialog();
            }
            query();
        }

        private void tsbSave_Click(object sender, EventArgs e)
        {
            endEditAndSave();
        }

        private void tsbExit_Click(object sender, EventArgs e)
        {
            if (hasChanges)
            {
                DialogResult result = Msg.YesNoCancelQuestionMsg(Messages.Yra_pakeitimu_Ar_issaugoti);

                if (result == DialogResult.No)  // pakeitimų yra, bet neišsaugoti
                {
                    Close();
                }
                else if (result == DialogResult.Cancel) // pakeitimų yra, bet nutraukti veiksmą
                {
                    return;
                }
                else   // pakeitimų yra ir išsaugoti
                {
                    endEditAndSave();
                    Close();
                }
            }
            else // pakeitimų nėra - išeiti ir viskas
            {
                Close();
            }
        }

        private void tsbFilterAddPos_Click(object sender, EventArgs e)
        {
            // filtruoti įrašus pagal pasirinktų langelių reikšmes

            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;

            int minrw = veryTopRow(selCells);
            // formuoti filtrą iš aukščiausios eilutės elementų
            foreach (DataGridViewCell cl in selCells)
            {
                // nefiltruoti, jeigu nieko nerodo arba rodo id
                if (cl.ColumnIndex < 1 || cl.RowIndex < 0 || cl.RowIndex > minrw) continue;

                filterElements.Add(makeFilterByCell(cl));
            }
            doFilter();
        }

        private void tsbFilterAddNeg_Click(object sender, EventArgs e)
        {
            // neigiamas filtras pagal pasirinktų langelių reikšmes

            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;            

            // formuoti filtrą iš aukščiausios eilutės elementų
            int minrw = veryTopRow(selCells);
            foreach (DataGridViewCell cl in selCells)
            {
                // nefiltruoti, jeigu nieko nerodo arba rodo id
                if (cl.ColumnIndex < 1 || cl.RowIndex < 0 || cl.RowIndex > minrw) continue;

                filterElements.Add(string.Format("NOT({0})", makeFilterByCell(cl)));
            }
            doFilter();
        }

        private void tsbFilterDrop_Click(object sender, EventArgs e)
        {
            // numeta filtrą ir rūšiavimą
            unfilter();
        }

        private void tsbFilterRemoveTail_Click(object sender, EventArgs e)
        {
            if (filterElements.Count > 0)
                filterElements.RemoveAt(filterElements.Count-1);
            doFilter();
        }

        private void tsbAddOrderAsc_Click(object sender, EventArgs e)
        {
            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;

            string leftCol = veryLeftCol(selCells);

            foreach (rikiavimas rik in rikiavimai)
            {
                if (rik.columnName == leftCol)
                {
                    Msg.ExclamationMsg(string.Format(Messages.Pagal_toki_jau_rikiuota, leftCol));
                    return;
                }
            }
            rikiavimai.Add(new rikiavimas(leftCol, true));
            doOrder();
        }

        private void tsbAddOrderDesc_Click(object sender, EventArgs e)
        {
            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;

            string leftCol = veryLeftCol(selCells);

            foreach (rikiavimas rik in rikiavimai)
            {
                if (rik.columnName == leftCol)
                {
                    Msg.ExclamationMsg(string.Format(Messages.Pagal_toki_jau_rikiuota, leftCol));
                    return;
                }
            }

            rikiavimai.Add(new rikiavimas(leftCol, false));
            doOrder();
        }

        private void tsbOrderByPlace_Click(object sender, EventArgs e)
        {
            string[] kodas = {"k11", "k12", "k21", "k22", "k23", "k24", "k31", "k32", "k41", "k42", "k51"};
            foreach (rikiavimas rik in rikiavimai)
            {
                foreach (string colname in kodas)
                {
                    if (rik.columnName == colname)
                    {
                        Msg.ExclamationMsg(string.Format(Messages.Pagal_toki_jau_rikiuota, colname));
                        return;
                    }
                }
            }
            
            rikiavimai.Add(new rikiavimas("k11", true));
            rikiavimai.Add(new rikiavimas("k12", true));
            rikiavimai.Add(new rikiavimas("k21", true));
            rikiavimai.Add(new rikiavimas("k22", true));
            rikiavimai.Add(new rikiavimas("k23", true));
            rikiavimai.Add(new rikiavimas("k24", true));
            rikiavimai.Add(new rikiavimas("k31", true));
            rikiavimai.Add(new rikiavimas("k32", true));
            rikiavimai.Add(new rikiavimas("k41", true));
            rikiavimai.Add(new rikiavimas("k42", true));
            rikiavimai.Add(new rikiavimas("k51", true));
            doOrder();
        }

        private void tsbDropOrder_Click(object sender, EventArgs e)
        {
            rikiavimai.Clear();
            dView.Sort = "";
        }

        private void doOrder()
        {
            string sortOrder = string.Empty;
            foreach (rikiavimas rik in rikiavimai)
            {
                sortOrder += rik.columnName + (rik.ascending ? string.Empty : " DESC") + ", ";
            }

            dView.Sort = sortOrder.Remove(sortOrder.Length - 2);
            updateStatusBar();
        }

        private int veryTopRow(DataGridViewSelectedCellCollection collection)
        {
            // rasti pirmosios eilutės indexą
            if (collection.Count == 0) return -1;

            int minrw = collection[0].RowIndex;
            foreach (DataGridViewCell cl in collection)
            {
                if (cl.RowIndex < minrw) minrw = cl.RowIndex;
            }
            return minrw;
        }

        private string veryLeftCol(DataGridViewSelectedCellCollection collection)
        {
            // rasti kairiausiojo stulpelio pavadinimą
            if (collection.Count == 0) return string.Empty;

            int veryLeftColIndex = collection[0].ColumnIndex;
            foreach (DataGridViewCell cl in collection)
            {
                if (cl.ColumnIndex < veryLeftColIndex)
                    veryLeftColIndex = cl.ColumnIndex;
            }
            return dgvAktai.Columns[veryLeftColIndex].Name;
        }

        private void tsbDeleteRecord_Click(object sender, EventArgs e)
        {
            if (dgvAktai.SelectedRows.Count != 1) return;
            string sqlDelete = "DELETE FROM Aktai WHERE id={0};";
            int id = Convert.ToInt32(dgvAktai.SelectedRows[0].Cells["id"].Value);

            // Paskutinį kartą patikslinama, ar tikrai ištrinti
            if (Msg.YesNoQuestionMsg(Messages.Ar_tikrai_istrinti) == DialogResult.No)
            {
                return;
            }
            DbHelper.executeNonQuery(string.Format(sqlDelete, id));

            query();
        }

        # region kol kas neveikiantis OR
        /*
        private void spbAddPosFilter_ButtonClick(object sender, EventArgs e)
        {
            // filtruoti įrašus pagal pasirinktų langelių reikšmes

            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;

            int minrw = veryTopRow(selCells);
            // formuoti filtrą iš aukščiausios eilutės elementų
            foreach (DataGridViewCell cl in selCells)
            {
                // nefiltruoti, jeigu nieko nerodo arba rodo id
                if (cl.ColumnIndex < 1 || cl.RowIndex < 0 || cl.RowIndex > minrw) continue;

                filterElements.Add(makeFilterByCell(cl));
            }
            doFilter();
        }

        private void mnAnd_Click(object sender, EventArgs e)
        {
            // filtruoti įrašus pagal pasirinktų langelių reikšmes

            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;

            int minrw = veryTopRow(selCells);
            // formuoti filtrą iš aukščiausios eilutės elementų
            foreach (DataGridViewCell cl in selCells)
            {
                // nefiltruoti, jeigu nieko nerodo arba rodo id
                if (cl.ColumnIndex < 1 || cl.RowIndex < 0 || cl.RowIndex > minrw) continue;

                filterElements.Add(makeFilterByCell(cl));
            }
            doFilter();
        }

        private void mnOr_Click(object sender, EventArgs e)
        {
            // filtruoti įrašus pagal pasirinktų langelių reikšmes

            DataGridViewSelectedCellCollection selCells = dgvAktai.SelectedCells;
            if (selCells.Count == 0) return;

            int minrw = veryTopRow(selCells);
            // formuoti filtrą iš aukščiausios eilutės elementų
            foreach (DataGridViewCell cl in selCells)
            {
                // nefiltruoti, jeigu nieko nerodo arba rodo id
                if (cl.ColumnIndex < 1 || cl.RowIndex < 0 || cl.RowIndex > minrw) continue;

                filterElements.Add(makeFilterByCell(cl));
            }
            cc = or;
            doFilter();
        }
        */
        # endregion
    }
}
